package datamining.algorithms.prefixspan;

import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import javax.swing.plaf.LayerUI;

import datamining.miner.chain.Extension;
import datamining.miner.enviroment.ThreadEnvironment;
import datamining.miner.general.Embedding;
import datamining.miner.general.ExtendedEmbedding;
import datamining.miner.general.Frequency;
import datamining.miner.general.IndexedSequence;
import datamining.sequence.IndexedItem;
import datamining.sequence.Sequence;

/**
 * <p>
 * 创建于 2012-12-8 下午9:31:31
 * 
 * @author xujinghu (jinghuxu@nudt.edu.cn) <br>
 *         Copyright 2012 xujinghu <br>
 *         Lisence: Apache
 */
public class PrefixSpanEmbedding<ItemType> implements ExtendedEmbedding<ItemType> {
	public static int counter = 0;
	private transient PrefixSpanSequence<ItemType> superSequence;
	private Sequence<ItemType> subSequence;
	private Map<IndexedItem<ItemType>, IndexedItem<ItemType>> prefixMap;

	/* final */transient PThreadEnvironment<ItemType> tenv;

	/** used for the pool */
	transient PrefixSpanEmbedding<ItemType> next;

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public PrefixSpanEmbedding(PThreadEnvironment<ItemType> tenv){
		this.tenv = tenv;
	}
	
	public PrefixSpanEmbedding(
			Sequence<ItemType> subSequence,
			PrefixSpanSequence<ItemType> superSequence,
			Map<IndexedItem<ItemType>, IndexedItem<ItemType>> prefixMap) {
		this.subSequence = subSequence;
		this.superSequence = superSequence;
		this.prefixMap = prefixMap;
	}

	/* 
	 * 复制本embedding，对prefixMap进行了复制，保留了superSequence, subSequence
	 */
	public PrefixSpanEmbedding<ItemType> clone(){
		//Sequence<ItemType> newSubSequence = subSequence.clone();
		Map<IndexedItem<ItemType>, IndexedItem<ItemType>> newPrefixMap = new TreeMap<IndexedItem<ItemType>, IndexedItem<ItemType>>();
		newPrefixMap.putAll(prefixMap);
		return new PrefixSpanEmbedding<ItemType>(subSequence, superSequence, newPrefixMap);
	}
	
	
	/**
	 * @author xujinghu
	 * @date 2012-12-18下午7:53:22
	 * @param ext
	 *                存储此embedding扩展后的embedding
	 * @param superExtendItem
	 *                父序列中的扩展项
	 * @return 扩展后的embedding
	 */
	public Embedding<ItemType> extend(Extension<ItemType> ext,
			IndexedItem<ItemType> superExtendItem) {
		return new LazyExtendedEmbedding<ItemType>(ext, superExtendItem, this);// 将embedding扩展推迟到必须进行的时候
	}

	@Override
	public Frequency frequency() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public IndexedSequence<ItemType> getIndexedSequence() {
		return superSequence;
	}

	public Map<IndexedItem<ItemType>, IndexedItem<ItemType>> getMap(){
		return this.prefixMap;
	}

	@Override
	public Sequence<ItemType> getSubSequence() {
		return subSequence;
	}

	@Override
	public IndexedItem<ItemType> getSubSequenceItem(
			IndexedItem<ItemType> superItem) {
		IndexedItem<ItemType> o = null;
		// ArrayList all=new ArrayList(); //建一个数组用来存放符合条件的KEY值
		/*
		 * 这里关键是那个entrySet()的方法,它会返回一个包含Map.Entry集的Set对象.
		 * Map.Entry对象有getValue和getKey的方法,利用这两个方法就可以达到从值取键的目的了 *
		 */
		Set<Entry<IndexedItem<ItemType>, IndexedItem<ItemType>>> set = prefixMap
				.entrySet();
		Iterator<Entry<IndexedItem<ItemType>, IndexedItem<ItemType>>> it = set
				.iterator();
		while (it.hasNext()) {
			Entry<IndexedItem<ItemType>, IndexedItem<ItemType>> entry = it
					.next();
			if (entry.getValue().equals(superItem)) {
				o = entry.getKey();
				// all.add(o); //把符合条件的项先放到容器中,下面再一次性打印出
			}
		}
		// return all;
		return o;
	}

	@Override
	public Sequence<ItemType> getSuperSequence() {
		return superSequence.toSequence();
	}

	@Override
	public IndexedItem<ItemType> getSuperSequenceItem(
			IndexedItem<ItemType> subItem) {
		// TODO Auto-generated method stub
		return prefixMap.get(subItem);
	}

	@Override
	public boolean mapExtension(Extension<ItemType> ext) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int mapExtension(Extension<ItemType> ext, BitSet allowedItems) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean overlaps(Embedding<ItemType> other,
			Collection<ItemType> ignore) {
		// TODO Auto-generated method stub
		return false;
	}

	public void release(final ThreadEnvironment<ItemType> target) {
		if (target == tenv) {
			tenv.push(this);
		}
	}

	public void setSubSequence(Sequence<ItemType> subSequence){
		this.subSequence = subSequence;
	}

	public String toString() {
		String str = "";
		str += "subSequence = " + this.subSequence + "\n"
				+ "superSequence = " + this.superSequence
				+ "\n";
		return str;
	}
}
